var mapportal = {
  map: null, // The OpenLayers map object
  panel: null, // The OpenLayers toolbar panel
  ctrl_pt: null, // Toolbar controls for drawing point
  ctrl_bbox: null, // Toolbar controls for drawing bounding box
  ctrl_poly: null, // Toolbar controls for drawing polygon
  vlayer: null, // Vector layer to which the feature would be added.
  show_editing_toolbar: 0,
  onAddFeatureClearPreviousFeatures: 0,
  
  MapServerURL: '/cgi-bin/mapserv',

  onMapInitComplete: null, // function callback on map init complete
  onFeatureAdded: null, // function callback on feature added
  getAddressForFeature: null, // function callback when feature has been added and reverse geocoding has been done.
  onUpdateTabsUI: null, // function callback when 

  NUMZOOMLEVEL: 19,

  base_map_projection: "EPSG:900913",
  default_projection: "EPSG:4326",

  map_init: function() {
    // increase reload attempts
    OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3;

    /*
    var options = {
      controls: [
        new OpenLayers.Control.Navigation() // add navigation control
        ,new OpenLayers.Control.PanZoomBar({zoomWorldIcon:true}) // add pan zoom bar icon
        //,new OpenLayers.Control.ScaleLine() // add map scale
        ,new OpenLayers.Control.MousePosition() // add mouse position control
      ]
      ,projection: new OpenLayers.Projection("EPSG:900913")
      ,displayProjection: new OpenLayers.Projection("EPSG:4326")
      ,units: "m"
      ,numZoomLevels: 18
      ,maxResolution: 156543.0339
      ,maxExtent: new OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508.34)
    };
    */

    var options = {
      controls: [
        new OpenLayers.Control.PanZoom()
        ,new OpenLayers.Control.MousePosition() // add mouse position control
        ,new OpenLayers.Control.LayerSwitcher()
      ]
      ,projection: new OpenLayers.Projection("EPSG:900913")
      ,displayProjection: new OpenLayers.Projection("EPSG:4326")
      ,units: "m"
      ,numZoomLevels: 18
      ,maxResolution: 156543.0339
      ,maxExtent: new OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508.34)
    };

    mapportal.map = new OpenLayers.Map('map', options);
    //mapportal.map.addControl(new OpenLayers.Control.MousePosition()); // add mouse position control

    // to get the xy values from the event object.mandatory in OL 2.7
    OpenLayers.Events.prototype.includeXY = true;

    mapportal.addGoogleBaseMaps();
    mapportal.createToolbarPanel();
    //showEditingToolbar();

    mapportal.set_init_center();

    //jQuery(".olControlScaleLine").css("bottom","60px");
    //jQuery(".olControlScaleLine").css("left","5px");

    /*
    var highlightCtrl = new OpenLayers.Control.SelectFeature(vlayer, {
    hover: true, highlightOnly: true, renderIntent: "temporary",
                        eventListeners: { featurehighlighted: onMouseOver,
    featureunhighlighted: onMouseOut } });

    //the order in which you add these lines seems to matter!
    map.addControl(highlightCtrl);
    highlightCtrl.activate();

    var pt = new OpenLayers.Geometry.Point(mapportal.center_lon, mapportal.center_lat);
    pt.transform(mapportal.map.displayProjection, mapportal.map.getProjectionObject());
    var circle = OpenLayers.Geometry.Polygon.createRegularPolygon(pt, mapportal.map.getScale() / (mapportal.map.zoom * 100), 50);
    mapportal.vlayer.addFeatures([new OpenLayers.Feature.Vector(circle)]);
    */

    mapportal.addEventHandlers();

    if (mapportal.onMapInitComplete) {
      mapportal.onMapInitComplete();
    } else {
      mapportal.onMapInitComplete = true;
    }
  },

  set_init_center: function() {
    var point = new OpenLayers.LonLat(mapportal.center_lon, mapportal.center_lat);
    point.transform(mapportal.map.displayProjection,mapportal.map.getProjectionObject());
    mapportal.map.setCenter(point, mapportal.default_zoom);
  },
  
  addEventHandlers: function() {
    // add featureadded event for vector layer
    mapportal.vlayer.events.on({
      "featureadded": mapportal.featureAdded
    });
  },

  /*
  var highlighted_polygon;

  function onMouseOver(event) {
    highlighted_polygon = OpenLayers.Geometry.Polygon.createRegularPolygon(event.feature.geomtery, 100, 20, 0);
    vlayer.addFeatures([highlighted_polygon]);
  }

  function onMouseOut(event) {
    vlayer.destroyFeatures([highlighted_polygon]);
  }
  */

  addGoogleBaseMaps: function() {
    OpenLayers.Layer.Google.prototype.RESOLUTIONS = [
      1.40625, 0.703125, 0.3515625, 0.17578125, 0.087890625, 0.0439453125, 0.02197265625,
      0.010986328125, 0.0054931640625, 0.00274658203125, 0.001373291015625, 0.0006866455078125,
      0.00034332275390625, 0.000171661376953125, 0.0000858306884765625, 0.00004291534423828125,
      0.000021457672119140625, 0.0000107288360595703125, 0.00000536441802978515625,
      0.000002682209014892578125, 0.0000013411045074462890625,
      0.00000067055225372314453125
    ];

    var ghyb = new OpenLayers.Layer.Google(
        "Google Hybrid",
        {type: G_HYBRID_MAP, numZoomLevels: 20, 'sphericalMercator': true}
    );
    var gphy = new OpenLayers.Layer.Google(
        "Google Physical",
        {type: G_PHYSICAL_MAP, 'sphericalMercator': true}
    );
    var gmap = new OpenLayers.Layer.Google(
        "Google Streets", // the default
        {numZoomLevels: 20, 'sphericalMercator': true}
    );
    var gsat = new OpenLayers.Layer.Google(
        "Google Satellite",
        {type: G_SATELLITE_MAP, numZoomLevels: 20, 'sphericalMercator': true}
    );

    // init the vector layer to add the features
    mapportal.vlayer = new OpenLayers.Layer.Vector("vector_layer");
    mapportal.vlayer.displayInLayerSwitcher = false;

    mapportal.map.addLayers([ghyb, gphy, gmap, gsat, mapportal.vlayer]);
  },

  createToolbarPanel: function() {
    // Multiple objects can share listeners with the same scope
    var zoomListeners = {
      "activate": mapportal.onZoomActivate,
      "deactivate": mapportal.onZoomDeactivate
    };

    // create zoomBox control object
    var zb = new OpenLayers.Control.ZoomBox({
      eventListeners: zoomListeners,
      title:"Click and draw a box to zoom into an area"
    });

    // create mouseDefaults(navigation icon) object
    var md = new OpenLayers.Control.MouseDefaults({
      title:'Click and drag to pan'
    });

    // create toolbar panel object
    mapportal.panel = new OpenLayers.Control.Panel({
      defaultControl: md
    });

    // add mouseDefaults and zoomBox controls to the toolbar panel
    mapportal.panel.addControls([
      md,
      zb
    ]);

    // add the toolbar panel to map.
    mapportal.map.addControl(mapportal.panel);
  },

  showEditingToolbar: function() {
    mapportal.show_editing_toolbar = 1;
    mapportal.addEditControlsToToolbarPanel();
    jQuery("#tabsMapportal").show();
  },

  hideEditingToolbar: function() {
    mapportal.show_editing_toolbar = 0;
    mapportal.addEditControlsToToolbarPanel();
    jQuery("#tabsMapportal").hide();
  },

  addEditControlsToToolbarPanel: function() {
    if (mapportal.show_editing_toolbar) {
      // control to add point
      if (!mapportal.ctrl_pt) { // If the control has not already been initialized
        mapportal.ctrl_pt = new OpenLayers.Control.DrawFeature(mapportal.vlayer, OpenLayers.Handler.Point, {'displayClass': 'olControlDrawFeaturePoint'});
        mapportal.ctrl_pt.title = 'DrawFeaturePoint';
      }

      // control to add bounding box
      if (!mapportal.ctrl_bbox) { // If the control has not already been initialized
        polyOptions = {sides: 4, irregular: true};
        mapportal.ctrl_bbox = new OpenLayers.Control.DrawFeature(mapportal.vlayer, OpenLayers.Handler.RegularPolygon, {handlerOptions: polyOptions, 'displayClass': 'olControlDrawFeatureBoundingBox'});
        mapportal.ctrl_bbox.title = 'DrawFeatureBoundingBox';
      }

      // control to add polygon
      if (!mapportal.ctrl_poly) { // If the control has not already been initialized
        mapportal.ctrl_poly = new OpenLayers.Control.DrawFeature(mapportal.vlayer, OpenLayers.Handler.Polygon, {'displayClass': 'olControlDrawFeaturePolygon'});
        mapportal.ctrl_poly.title = 'DrawFeaturePolygon';
      }

      mapportal.panel.addControls([mapportal.ctrl_pt, mapportal.ctrl_bbox, mapportal.ctrl_poly]);
    } else {
      mapportal.resetControlPanel();
    }
  },

  resetControlPanel: function() {
    if (mapportal.ctrl_pt != null) {
      mapportal.ctrl_pt.deactivate();
      OpenLayers.Util.removeItem(mapportal.panel.controls, mapportal.ctrl_pt);
      var len = mapportal.map.getLayersByName("OpenLayers.Handler.Point").length;
      for(i = 0; i < len; i++) {
        mapportal.map.getLayersByName("OpenLayers.Handler.Point")[i].destroy();
      }
    }

    if (mapportal.ctrl_bbox != null) {
      mapportal.ctrl_bbox.deactivate();
      OpenLayers.Util.removeItem(mapportal.panel.controls, mapportal.ctrl_bbox);
      var len = mapportal.map.getLayersByName("OpenLayers.Handler.RegularPolygon").length;
      for(i = 0; i < len; i++) {
        mapportal.map.getLayersByName("OpenLayers.Handler.RegularPolygon")[i].destroy();
      }
    }

    if (mapportal.ctrl_poly != null) {
      mapportal.ctrl_poly.deactivate();
      OpenLayers.Util.removeItem(mapportal.panel.controls, mapportal.ctrl_poly);
      len = mapportal.map.getLayersByName("OpenLayers.Handler.Polygon").length;
      for(i = 0; i < len; i++) {
        mapportal.map.getLayersByName("OpenLayers.Handler.Polygon")[i].destroy();
      }
    }

    mapportal.panel.redraw();

    mapportal.activateNavigationControl();
  },

  onZoomActivate: function(event) {
    jQuery("#map")[0].style.cursor = "url(sites/all/modules/map/images/zoom-to-extent.png),auto";
  },

  onZoomDeactivate: function(event) {
    jQuery("#map")[0].style.cursor = "";
  },

  activateNavigationControl: function() {
    // Activate navigation control
    mapportal.activateToolbarControl(mapportal.panel.controls[0]);
  },

  activateToolbarControl: function(ctrl) {
    // Deactivate all controls in toolbar.
    var len = mapportal.panel.controls.length;
    for (var i = 0; i < len; i++) {
      if (mapportal.panel.controls[i] == ctrl) {
        mapportal.panel.controls[i].activate();
      } else {
        mapportal.panel.controls[i].deactivate();
      }
    }
  },

  featureAdded: function(event) {
    if (mapportal.onAddFeatureClearPreviousFeatures) {
      var vl = mapportal.vlayer;
      var features = vl.features;
      var remFeatures = [];
      if (features.length > 1) {
        for (var i = 0; i < features.length; i++ ) {
          if (features[i] != event.feature) {
            //features.splice(i,1);
            remFeatures.push(features[i]);
          }
        }
        vl.destroyFeatures(remFeatures);
      }
    }

    var geom = event.feature.geometry.clone();
    mapportal._featureAdded(geom);

    if (mapportal.getAddressForFeature) {
      var bounds = null;
      bounds = geom.getBounds();
      bounds.transform(mapportal.map.getProjectionObject(), mapportal.map.displayProjection);
      var lonlat = bounds.getCenterLonLat();
      mapportal.getLatLonAddress(lonlat.lat, lonlat.lon);
    }
  },

  _featureAdded: function(geometry) {
    var geom = geometry.clone();
    geom.transform(mapportal.map.getProjectionObject(), mapportal.map.displayProjection);
    var topo = geom.toString();
    mapportal.updateTabsUI(topo);
    if (mapportal.onFeatureAdded) {
      mapportal.onFeatureAdded(geom.toString());
    }
  },

  markPoint: function() {
    mapportal.activateToolbarControl(mapportal.ctrl_pt);

    var lat = jQuery("#txtMPPtLat").val();
    var lon = jQuery("#txtMPPtLon").val();

    var err = '';
    if (!mapportal.isValidLat(lat)) {
      err = "Please enter valid values for latitude.\n";
    }
    if (!mapportal.isValidLon(lon)) {
      err += "Please enter valid values for longitude.";
    }

    if (err != '') {
      alert(err);
      return;
    }
    mapportal.addPoint(lon, lat);
    var pt = new OpenLayers.Geometry.Point(lon, lat).transform(mapportal.map.displayProjection, mapportal.map.getProjectionObject());
    mapportal._featureAdded(pt);
    pt = new OpenLayers.LonLat(lon, lat).transform(mapportal.map.displayProjection, mapportal.map.getProjectionObject());
    mapportal.map.panTo(pt);
  },

  markBoundingBox: function() {
    mapportal.activateToolbarControl(mapportal.ctrl_bbox);

    var tlLat = jQuery("#txtMPBBoxTLLat").val();
    var tlLon = jQuery("#txtMPBBoxTLLon").val()
    var brLat = jQuery("#txtMPBBoxBRLat").val();
    var brLon = jQuery("#txtMPBBoxBRLon").val()

    var err = '';
    if (!mapportal.isValidLat(tlLat)) {
      err = "Please enter valid values for top-left latitude.\n";
    }
    if (!mapportal.isValidLon(tlLon)) {
      err += "Please enter valid values for top-left longitude.";
    }
    if (!mapportal.isValidLat(brLat)) {
      err = "Please enter valid values for bottom-right latitude.\n";
    }
    if (!mapportal.isValidLon(brLon)) {
      err += "Please enter valid values for bottom-right longitude.";
    }

    if (err != '') {
      alert(err);
      return;
    }

    var bounds = new OpenLayers.Bounds(tlLon, tlLat, brLon, brLat);
    bounds.transform(mapportal.map.displayProjection, mapportal.map.getProjectionObject());
    var poly = bounds.toGeometry();
    mapportal.vlayer.destroyFeatures();
    mapportal.vlayer.addFeatures([new OpenLayers.Feature.Vector(poly)]);
    mapportal.map.zoomToExtent(bounds);
    mapportal._featureAdded(poly);
  },

  updateTabsUI: function(topo) {
    if (jQuery('#tabsMapportal').length == 0) {
      return;
    }
    var re, matchedArr;
    if (mapportal.ctrl_pt.active) {
      jQuery('#tabsMapportal').tabs('option', 'selected', 0);
      re = new RegExp("(.*)[\(](.*)[ ](.*)[)]", "m");
      matchedArr = topo.match(re);
      jQuery("#txtMPPtLat").val(matchedArr[3]);
      jQuery("#txtMPPtLon").val(matchedArr[2]);
      jQuery("#txtMPBBoxTLLat").val("");
      jQuery("#txtMPBBoxTLLon").val("");
      jQuery("#txtMPBBoxBRLat").val("");
      jQuery("#txtMPBBoxBRLon").val("");
    } else if (mapportal.ctrl_bbox.active) {
      jQuery('#tabsMapportal').tabs('option', 'selected', 1);
      re = new RegExp("(.*)[\(][\(](.*)[ ](.*)[,](.*)[,](.*)[ ](.*)[,](.*)[,](.*)[)][)]", "m");
      matchedArr = topo.match(re);
      jQuery("#txtMPPtLat").val("");
      jQuery("#txtMPPtLon").val("");
      jQuery("#txtMPBBoxTLLat").val(matchedArr[3]);
      jQuery("#txtMPBBoxTLLon").val(matchedArr[2]);
      jQuery("#txtMPBBoxBRLat").val(matchedArr[6]);
      jQuery("#txtMPBBoxBRLon").val(matchedArr[5]);
    } else if (mapportal.ctrl_poly.active) {
      jQuery('#tabsMapportal').tabs('option', 'selected', 2);
      jQuery("#txtMPPtLat").val("");
      jQuery("#txtMPPtLon").val("");
      jQuery("#txtMPBBoxTLLat").val("");
      jQuery("#txtMPBBoxTLLon").val("");
      jQuery("#txtMPBBoxBRLat").val("");
      jQuery("#txtMPBBoxBRLon").val("");
    }
    
    if (mapportal.onUpdateTabsUI) {
      mapportal.onUpdateTabsUI(topo);
    }
  },

  addPoint: function(lon, lat) {
    var pt = new OpenLayers.Geometry.Point(lon, lat);
    pt.transform(mapportal.map.displayProjection, mapportal.map.getProjectionObject());
    mapportal.map.setCenter(pt);
    var pointFeature = new OpenLayers.Feature.Vector(pt);
    var style = OpenLayers.Util.extend({}, OpenLayers.Feature.Vector.style['default']);

    /*
    style.graphicOpacity = 0.9;
    style.pointRadius =  5;
    style.strokeColor = "#000000";
    style.strokeOpacity = 1;
    style.strokeWidth = 1;
    */
    /*
    style.cursor =  "pointer";
    //style.graphicXOffset = -(style.pointRadius * 0.66);
    //style.graphicYOffset = -(style.pointRadius * 1.9);
    style.graphicXOffset = -(style.pointRadius * 0.91);
    style.graphicYOffset = -(style.pointRadius * 1.89);
    */

    //style.externalGraphic = "/OpenLayers/img/marker.png";
    pointFeature.style = style;
    mapportal.vlayer.addFeatures([pointFeature]);
  },

  gotoAddress: function(address) {
    if (address == 'World') {
      mapportal.set_init_center();
    }
    else {
      var geocoder = new GClientGeocoder();
      geocoder.getLocations(
        address,
        function(resp) {
          if (resp.Status.code == '200') {
            var info = resp.Placemark[0];
            var point = info.Point.coordinates;
            var pt = new OpenLayers.LonLat(point[0], point[1]);
            //pt.transform(new OpenLayers.Projection(default_projection), map.getProjectionObject());
            pt.transform(mapportal.map.displayProjection, mapportal.map.getProjectionObject());

            mapportal.map.setCenter(pt);

            var latlonbox = info.ExtendedData.LatLonBox;
            //var bounds = new OpenLayers.Bounds(tlLon, tlLat, brLon, brLat);
            var bounds = new OpenLayers.Bounds(latlonbox.west, latlonbox.south, latlonbox.east, latlonbox.north);
            bounds.transform(mapportal.map.displayProjection, mapportal.map.getProjectionObject());
            mapportal.map.zoomToExtent(bounds);
          }
          else {
          }
        }
      );
    }
  },

  getLatLonAddress: function(lat, lon) {
    var geocoder = new GClientGeocoder();
    geocoder.getLocations(
      new GLatLng(lat, lon),
      function (resp) {
        if (resp.Status.code == '200') {
          var info = resp.Placemark[0];
          var addrDetails = info.AddressDetails;
          var details = new Object();
          details.country = '';
          details.region = '';
          details.city = '';
          if (addrDetails.Country) {
            var countryinfo = addrDetails.Country
            details.country = countryinfo.CountryName;
            if (countryinfo.AdministrativeArea) {
              var a = countryinfo.AdministrativeArea;
              details.region = a.AdministrativeAreaName;
              if (a.SubAdministrativeArea) {
                var b = a.SubAdministrativeArea;
                details.city = b.SubAdministrativeAreaName;
              }
            }
          }
          mapportal.getAddressForFeature(details);
        }
        else {
        }
      }
    );
  },

  isFloat: function(x) {
    var y = parseFloat(x);
    if (isNaN(y)) return false;
    return x == y && x.toString() == y.toString();
  },

  isValidLat: function(lat) {
    if (!mapportal.isFloat(lat)) {
      return false;
    }
    if (lat < -90 || lat > 90) {
      return false;
    } else {
      return true;
    }
  },

  isValidLon: function(lon) {
    if (!mapportal.isFloat(lon)) {
      return false;
    }
    if (lon < -180 || lon > 180) {
      return false;
    } else {
      return true;
    }
  },

  onClickGotoAddr: function() {
    //jQuery.watermark.hideAll();
    var addr = jQuery("#txtMPAddress").val();
    if (addr != "") {
      mapportal.gotoAddress(addr);
    }
    //jQuery.watermark.showAll();
  },

  addFeatureFromWKT: function(wkt) {
    var in_options = {
        'internalProjection': mapportal.map.getProjectionObject(),
        'externalProjection': mapportal.map.displayProjection
    };

    var out_options = {
        'internalProjection': mapportal.map.displayProjection,
        'externalProjection': mapportal.map.getProjectionObject()
    };

    // create a feature from a wkt string and add it to the map
    var parser = new OpenLayers.Format.WKT(in_options);
    var geometry = parser.read(wkt);
    mapportal.vlayer.addFeatures(geometry);

    if (wkt.match("^"+'POINT') == 'POINT') { // WKT starts with
      var llarr = wkt.replace("POINT(", "").replace(")", "").split(" ");
      var lonlat = new OpenLayers.LonLat(llarr[0], llarr[1]);
      lonlat.transform(mapportal.map.displayProjection,mapportal.map.getProjectionObject());
      mapportal.map.setCenter(lonlat);
      mapportal.activateToolbarControl(mapportal.ctrl_pt);
    }
    else if (wkt.match("^"+'POLYGON') == 'POLYGON') {
      // zoom to polygon
      mapportal.map.zoomToExtent(mapportal.vlayer.getDataExtent());

      if (mapportal.isPolygonRectangle(wkt)) {
        mapportal.activateToolbarControl(mapportal.ctrl_bbox);
      }
      else {
        mapportal.activateToolbarControl(mapportal.ctrl_poly);
      }
    }

    mapportal._featureAdded(geometry.geometry);
    hideTabs();
    //mapportal.vlayer.redraw();
  },

  isPolygonRectangle: function(wkt) {
    var arr = wkt.replace("POLYGON((", "").replace("))", "").split(',');
    if (arr.length == 5) {
      if (arr[0] == arr[4]) {
        var pt1 = arr[0].split(' ');
        var pt2 = arr[1].split(' ');
        var pt3 = arr[2].split(' ');
        var pt4 = arr[3].split(' ');
        if ((pt1[0] == pt2[0]) && (pt3[0] == pt4[0]) && (pt1[1] == pt4[1]) && (pt2[1] == pt3[1])) {
          return true;
        }
      }
    }
    return false;
  },
  
  addWMSLayer: function(mapfile, layer_name) {
    var twms = new OpenLayers.Layer.WMS(
      "Spandan, the bip",
      mapportal.MapServerURL,
      {
        map: mapfile,
        transparent: true,
        layers: layer_name,
        format: 'image/png',
        projection: mapportal.base_map_projection,
        reproject: false,
        units: "m"
      },
      {
        singleTile: false,
        isBaseLayer: false 
      }
    );
   
    twms.displayInLayerSwitcher = false; 
    mapportal.map.addLayers([twms]);
  }

}

function hideTabs() {
  var $tabs = jQuery("#tabsMapportal ul li");
  $tabs.removeClass("ui-tabs-selected");
  $tabs.removeClass("ui-state-active");

  $tabs.addClass("ui-state-default");

  jQuery("#tabsMapportal div.ui-tabs-panel:not(.ui-tabs-hide)").addClass("ui-tabs-hide");

  return false;
}

jQuery(document).ready(function(){
  if (jQuery("#tabsMapportal").length > 0) {
    jQuery("#tabsMapportal").tabs();
    //v//jQuery("#txtMPAddress").watermark("Enter address");
    jQuery("#btnMPPt").click(mapportal.markPoint);
    jQuery("#btnMPBBox").click(mapportal.markBoundingBox);

    jQuery(".close-map-tabs a").click(hideTabs);
    hideTabs();
  }
  jQuery("#btnMPGotoAddr").click(mapportal.onClickGotoAddr);
  //mapportal.map_init();
  window.onload = mapportal.map_init;
});
